package taskhandler

import (
	"strconv"
	"strings"
	"time"

	"cvevulner/common"
	"cvevulner/models"

	"github.com/astaxie/beego/logs"
)

func CheckCveOriginData(prcnum int) (string, error) {
	defer common.Catchs()
	//var os []models.OriginUpstream
	count := 0
	ok := models.UpdateOriginExistTemp()
	if !ok {
		logs.Info("UpdateOriginExistTemp, No data to process")
		return "", nil
	}
	for {
		os, num, err := models.QueryOriginCveE(prcnum)
		if err != nil || num == 0 {
			logs.Info("Currently no abnormal cve raw data processing, err: ", err,
				", Processing time range: beforetime: ",
				"curtime: ", common.GetCurTime())
			break
		}
		ch := make(chan int, len(os))
		for i, cveOrg := range os {
			count = count + 1
			go func(idx int, cveData models.OriginUpstream) {
				ch <- idx
				packNameList := []string{}
				if cveData.PackName != "" && len(cveData.PackName) > 0 {
					packNameList = strings.Split(cveData.PackName, ",")
				}
				if len(packNameList) > 0 {
					for _, pk := range packNameList {
						pkList := strings.Split(pk, "==")
						if len(pkList) == 2 {
							var gits models.GitOpenEuler
							gits.PackageName = pkList[0]
							gits.Version = pkList[1]
							gits.Status = 1
							ok := models.QueryCveOpeneulerdata(&gits)
							if !ok {
								opy := models.OpenGussYaml{PackageName: pkList[0], Version: pkList[1]}
								openErr := models.GetOpengaussYaml(&opy, "PackageName", "Version")
								if openErr == nil && opy.Id > 0 {
									models.UpdateOriginExist(common.GetCurTime(), cveData.PackName, cveData.Version, cveData.CveId, 1)
									logs.Info("Data added to the cve vulnerability: ", cveData, ", gits: ", gits)
									continue
								}
								if flag, _ := judgeSocpe(pkList[0], pkList[1]); flag {
									models.UpdateOriginExist(common.GetCurTime(), cveData.PackName, cveData.Version, cveData.CveId, 1)
									logs.Info("Correspondence between warehouse and version is wrong, restore: ", cveData, ", gits: ", gits)
									continue
								}
								opky := models.OpenLookengYaml{PackageName: pkList[0], Version: pkList[1]}
								opkyErr := models.GetOpenLookengYaml(&opky, "PackageName", "Version")
								if opky.Id > 0 {
									models.UpdateOriginExist(common.GetCurTime(), cveData.PackName, cveData.Version, cveData.CveId, 1)
									logs.Info("Correspondence between warehouse and version is wrong, restore: ", cveData, ", gits: ", gits, opkyErr)
									continue
								}
								models.UpdateOriginExist(common.GetCurTime(), cveData.PackName, cveData.Version, cveData.CveId, 0)
							} else {
								models.UpdateOriginExist(common.GetCurTime(), cveData.PackName, cveData.Version, cveData.CveId, 1)
								logs.Info("Data added to the cve vulnerability:", cveData, ", gits: ", gits)
							}
						}
					}
				} else {
					models.UpdateOriginExist(common.GetCurTime(), cveData.PackName, cveData.Version, cveData.CveId, 0)
					logs.Info("Data error, field is empty, PackName: ", cveData.PackName,
						",Version: ", cveData.Version, ", CveId, ", cveData.CveId)
				}
			}(i, cveOrg)
		}
		for i := 0; i < cap(ch); i++ {
			<-ch
		}
		close(ch)
	}
	return "", nil
}

func UpdateAbnCveStatus(prcNum, days int, cveSt string) (string, error) {
	beforeTime := common.GetBeforeTime(days)
	cveId := int64(0)
	for {
		cveData, err := models.QueryAbnCve(cveSt, beforeTime, prcNum, cveId)
		if err == nil && len(cveData) > 0 {
			for _, cd := range cveData {
				cveId = cd.CveId
				issueTmp := models.IssueTemplate{CveNum: cd.CveNum, CveId: cd.CveId, Repo: cd.PackName}
				err := models.GetIssueTemplateByColName(&issueTmp, "CveNum", "CveId", "Repo")
				if issueTmp.TemplateId < 1 {
					cd.Status = 0
					update := models.UpdateVulnCenter(&cd, "Status")
					if !update {
						logs.Error("update vulnCenter status fail ", cd, ", err: ", err)
						continue
					}
				} else {
					if issueTmp.IssueId < 1 || issueTmp.IssueNum == "" || len(issueTmp.IssueNum) < 2 {
						_, oks := models.QueryIssueCveByNum(cd.CveNum, cd.PackName, cd.OrganizationID)
						if oks {
							continue
						}
						models.DeleteIssueTemplate(issueTmp.TemplateId)
						cd.Status = 0
						update := models.UpdateVulnCenter(&cd, "Status")
						if !update {
							logs.Error("update vulnCenter status fail ", cd, ", err: ", err)
							continue
						}
					}
				}
			}
		} else {
			break
		}
	}
	return "", nil
}

func AddSaNumber(saReAmount int64) (string, error) {
	totalSaReAmount := 2 * saReAmount
	curYears := strconv.Itoa(time.Now().Year())
	saNum := int64(1001)
	models.DeleteSaNumberByYears(curYears, 1)
	var count int64
	count = models.GetSaNumCountByYears(curYears, 1)
	if count <= saReAmount {
		var sa models.SaNumber
		getErr := models.GetSaNumberByYears(&sa, curYears, 0, 2)
		logs.Info("AddSaNumber, getErr: ", getErr)
		if sa.SaId == 0 {
			for i := int64(0); i < totalSaReAmount; i++ {
				var localSa models.SaNumber
				localSa.OpenEulerSANum = "openEuler-SA-" + curYears + "-" + strconv.FormatInt(saNum, 10)
				localSa.Status = 1
				localSa.SaNum = saNum
				localSa.SaYears = curYears
				localSa.CreateTime = common.GetCurTime()
				models.InsertSaNumber(&localSa)
				saNum += 1
			}
		} else {
			saNum = sa.SaNum + 1
			for i := int64(0); i < totalSaReAmount-count; i++ {
				var localSa models.SaNumber
				localSa.OpenEulerSANum = "openEuler-SA-" + curYears + "-" + strconv.FormatInt(saNum, 10)
				localSa.Status = 1
				localSa.SaNum = saNum
				localSa.SaYears = curYears
				localSa.CreateTime = common.GetCurTime()
				models.InsertSaNumber(&localSa)
				saNum += 1
			}
		}
	}
	return "", nil
}
